package com.pony.iphone.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
//import com.pony.iphone.config.QuestionDefaultConfig;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.*;

/**
 * @author pony
 * @version 1.0
 * @description: TODO
 * @create 2025/8/20 00:00
 */
@Data
@AllArgsConstructor
//@NoArgsConstructor
@TableName(value = "t_question", autoResultMap = true)
public class Question {
    // 问题id
    private Long id;
    // 问题
    private String question;
    // 问题答案，以及答案对应的分数
    @TableField(typeHandler = JacksonTypeHandler.class)
    private HashMap<String, Long> answer;

    // 不映射数据库
    @TableField(exist = false)
    // 题库名称，默认是iphone题库
    private String libraryName;

//    // 无参构造，使用构造函数设置默认值
//    public Question() {
//        this.libraryName = QuestionDefaultConfig.getDefaultLibraryName();
//    }
//
//    // 使用构造函数设置默认值
//    public Question(String question, HashMap<String, Long> answer) {
//        this.question = question;
//        this.answer = answer;
//        this.libraryName = QuestionDefaultConfig.getDefaultLibraryName();
//    }

    /**
     * 随机获取一个答案
     * @return
     */
    public String getRandomAnswer(){
        // 1、非空校验
        if (this.answer == null || this.answer.isEmpty()) {
            return null;
        }

        // 2、hashmap -> list，keySet 就是将key值取出来组合成一个list
        List<String> keys = this.answer.keySet().stream().toList();
        int randomIndex = new Random().nextInt(keys.size());
        return keys.get(randomIndex);
    }

    /**
     * 伪随机（最大分数的偏移），计算权重，获取权重最大的答案，分数越大，权重越小，被随机选中的概率越小
     * @return 默认是返回第一个（一般不会出现）
     */
    public String getWeightAnswer(){
        // 1、非空校验
        if (this.answer == null || this.answer.isEmpty()) {
            return null;
        }

        // 2、先找出 HashMap 中的最大分数，没有最大值就返回0
        long maxScore = this.answer.values().stream()
                .mapToLong(Long::longValue)
                .max()
                .orElse(0L);

        /**
         * 3、计算总权重，先计算每个答案的权重值
         * 每个选项的权重 = 最大分数 + 1 - 当前分数
         * 然后求和计算总权重值
         */
        long totalWeight = this.answer.values().stream()
                .mapToLong(score -> maxScore + 1 - score)
                .sum();

        // 4、根据总权重值，计算出一个随机数
        long randomPoint = new Random().nextLong(totalWeight);

        // 5、根据权重选择，也就是看 randomPoint 落到了那个答案的区间里，在哪个区间里，就返回这个答案
        // 记录当前的一个权重范围
        long accumulatedWeight = 0;
        for (Map.Entry<String, Long> entry : this.answer.entrySet()) {
            //当前的一个权重范围 + 下一个选项的区间（权重值）
            accumulatedWeight += (maxScore + 1 - entry.getValue());
            if (randomPoint < accumulatedWeight) {
                return entry.getKey();
            }
        }

        // 默认返回第一个
        return this.answer.keySet().iterator().next();
    }
}
